var Drag = new Class({

	Implements: [Events, Options],

	options: {/*
		onBeforeStart: function(thisElement){},
		onStart: function(thisElement, event){},
		onSnap: function(thisElement){},
		onDrag: function(thisElement, event){},
		onCancel: function(thisElement){},
		onComplete: function(thisElement, event){},*/
		snap: 6,
		unit: 'px',
		grid: false,
		style: true,
		limit: false,
		handle: false,
		invert: false,
		preventDefault: false,
		stopPropagation: false,
		modifiers: {x: 'left', y: 'top'}
	},

	initialize: function(){
		var params = Array.link(arguments, {
			'options': Type.isObject,
			'element': function(obj){
				return obj != null;
			}
		});

		this.element = document.id(params.element);
		this.document = this.element.getDocument();
		this.setOptions(params.options || {});
		var htype = typeOf(this.options.handle);
		this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
		this.mouse = {'now': {}, 'pos': {}};
		this.value = {'start': {}, 'now': {}};

		this.selection = (Browser.ie) ? 'selectstart' : 'mousedown';


		if (Browser.ie && !Drag.ondragstartFixed){
			document.ondragstart = Function.from(false);
			Drag.ondragstartFixed = true;
		}

		this.bound = {
			start: this.start.bind(this),
			check: this.check.bind(this),
			drag: this.drag.bind(this),
			stop: this.stop.bind(this),
			cancel: this.cancel.bind(this),
			eventStop: Function.from(false)
		};
		this.attach();
	},

	attach: function(){
		this.handles.addEvent('mousedown', this.bound.start);
		return this;
	},

	detach: function(){
		this.handles.removeEvent('mousedown', this.bound.start);
		return this;
	},

	start: function(event){
		var options = this.options;

		if (event.rightClick) return;

		if (options.preventDefault) event.preventDefault();
		if (options.stopPropagation) event.stopPropagation();
		this.mouse.start = event.page;

		this.fireEvent('beforeStart', this.element);

		var limit = options.limit;
		this.limit = {x: [], y: []};

		var z, coordinates;
		for (z in options.modifiers){
			if (!options.modifiers[z]) continue;

			var style = this.element.getStyle(options.modifiers[z]);

			// Some browsers (IE and Opera) don't always return pixels.
			if (style && !style.match(/px$/)){
				if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
				style = coordinates[options.modifiers[z]];
			}

			if (options.style) this.value.now[z] = (style || 0).toInt();
			else this.value.now[z] = this.element[options.modifiers[z]];

			if (options.invert) this.value.now[z] *= -1;

			this.mouse.pos[z] = event.page[z] - this.value.now[z];

			if (limit && limit[z]){
				var i = 2;
				while (i--){
					var limitZI = limit[z][i];
					if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
				}
			}
		}

		if (typeOf(this.options.grid) == 'number') this.options.grid = {
			x: this.options.grid,
			y: this.options.grid
		};

		var events = {
			mousemove: this.bound.check,
			mouseup: this.bound.cancel
		};
		events[this.selection] = this.bound.eventStop;
		this.document.addEvents(events);
	},

	check: function(event){
		if (this.options.preventDefault) event.preventDefault();
		var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
		if (distance > this.options.snap){
			this.cancel();
			this.document.addEvents({
				mousemove: this.bound.drag,
				mouseup: this.bound.stop
			});
			this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
		}
	},

	drag: function(event){
		var options = this.options;

		if (options.preventDefault) event.preventDefault();
		this.mouse.now = event.page;

		for (var z in options.modifiers){
			if (!options.modifiers[z]) continue;
			this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];

			if (options.invert) this.value.now[z] *= -1;

			if (options.limit && this.limit[z]){
				if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
					this.value.now[z] = this.limit[z][1];
				} else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
					this.value.now[z] = this.limit[z][0];
				}
			}

			if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);

			if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
			else this.element[options.modifiers[z]] = this.value.now[z];
		}

		this.fireEvent('drag', [this.element, event]);
	},

	cancel: function(event){
		this.document.removeEvents({
			mousemove: this.bound.check,
			mouseup: this.bound.cancel
		});
		if (event){
			this.document.removeEvent(this.selection, this.bound.eventStop);
			this.fireEvent('cancel', this.element);
		}
	},

	stop: function(event){
		var events = {
			mousemove: this.bound.drag,
			mouseup: this.bound.stop
		};
		events[this.selection] = this.bound.eventStop;
		this.document.removeEvents(events);
		if (event) this.fireEvent('complete', [this.element, event]);
	}

});

Element.implement({

	makeResizable: function(options){
		var drag = new Drag(this, Object.merge({
			modifiers: {
				x: 'width',
				y: 'height'
			}
		}, options));

		this.store('resizer', drag);
		return drag.addEvent('drag', function(){
			this.fireEvent('resize', drag);
		}.bind(this));
	},
    makeMovable: function(options){	return new Drag(this, Object.merge({modifiers: {x: 'left', y: 'top'},preventDefault : true}, options));}

});


(function(ns, win, doc, undefined){
	ns.ModelDialog = new Class({
		Extends : ns.Base,
        Binds: ['close', '_close', 'prevent', 'ok', 'cancel'],
		options : {
			title : '',
			content : '',
			width : 500,
			height : 170,
			index : 999,
			'class' : 'smart',
			movable : true,
			selectable : true,
			mask : true,
			wait : true,
			closeDelay : 0,
			desc : {
				show : false,
				icon : '',
				title : '',
				content : ''
			},
			buttons : {
				ok : {text : '确定', show : true},
				cancel : {text : '取消', show : true}
			}/*,
			onClose : $empty,
			doValidate : $empty,
			doCancel : $empty,
			doOk : $empty*/
		},
		build : function(ops, self) {
			self.ie6 = Browser.ie && Browser.version < 7;
			var container = self.container = new Element('div', {'class' : ops['class'], styles : {position:'absolute', left : 0, top : 0}}).set('html', self.getHtml()).inject(doc.body);
			self.wrapper = container.getElement('table');
			
            self.opacity = container.getElement('.opacity');
			self.titler = container.getElement('div.title div');
			self.contenter = container.getElement('td.content');
			self.descHolder = container.getElement('tr.desc');
			self.descTitler = self.descHolder.getElement('h5');
			self.descContenter = self.descTitler.getNext('div');
			
			self.button = container.getElements('a').associate(['close', 'ok', 'cancel']);
			self.button.close.hideOutline();
			
			if(ops.movable) self.makeMovable();	
			this.update(ops);
		},
		getHtml : function(){
			var self = this,
                html = [], 
                IMGFOLDERPATH = 'css/img/', 
                ops = self.options;
			if (self.ie6) html.push('<iframe src="" frameborder="0" style="position:absolute;width:100%;height:100%;z-index:-1;filter:alpha(opacity=1);"></iframe>');
            html.push('<div class="opacity" style="width:' + (ops.width + 10) + 'px"></div>');
			html.push('<table ');
			if (!ops.selectable) html.push('style="-moz-user-select:none;" oncontextmenu="return false" onselectstart="return false"');
			html.push('border="0" cellpadding="0" cellspacing="0" style="width:' + ops.width + 'px">');
			html.push('  <tr class="move top">');
			html.push('    <td class="side top_left"><div></div></td>');
			html.push('    <td class="top_center"><div class="title"><div>' + ops.title + '</div></div></td>');
			html.push('    <td class="side top_right"><div></div></td>');
			html.push('  </tr>');
			html.push('  <tr><td class="middle_left"></td>');
			html.push('    <td align="center" valign="top">');
			html.push('    <table width="100%" border="0" cellpadding="0" cellspacing="0" style="background:#fff;">');
			html.push('        <tr class="desc">');
			html.push('          <td height="50" valign="top"><table border="0" cellspacing="0" cellpadding="8">');
			html.push('              <tr><td class="appicon"></td>');
			html.push('               <td align="left" style="line-height:16px;">');
			html.push('                <h5 class="fb"></h5>');
			html.push('                <div></div></td>');
			html.push('             </tr></table></td></tr>');
			html.push('        <tr><td class="content" style="padding-bottom:35px;width:' + ops.width + 'px;height:' + ops.height + 'px;vertical-align: middle;">');
			html.push(ops.content);
			html.push('          </td></tr>');
			html.push('        <tr><td class="button_container"></td></tr>');
			html.push('     </table></td>');
			html.push('    <td class="middle_right"></td></tr>');
			html.push('  <tr><td class="bottom_left"></td>');
			html.push('    <td class="bottom_center"></td>');
			html.push('    <td class="bottom_right"></td>');
			html.push('  </tr></table>');
			html.push(' <a class="close">X</a><a class="action ok"><div>OK</div></a><a class="action cancel"><div>Cancel</div></a>');
			return html;
		},
		observe : function(self, action, actions) {
			var btn = self.button;
			btn.close[action]('click', self._close);
			btn.ok[action]('click', self.ok);
			btn.cancel[action]('click', self.cancel);
		},
		prevent : function(e){
			e && e.preventDefault();
		},
		_close : function(e){
			e && e.preventDefault();
            var self = this;
			self.hideMask();
			self.container.hide();
			if (self.doClose) self.doClose(self);
			doc.fireEvent('click');
			return self;
		},
		close : function(e){
			e && e.preventDefault();
            var self = this;
			self.hideMask();
			self.container.hide();
			doc.fireEvent('click');
			return self;
		},
		makeMovable : function(){
            var self = this,
                moveObj;
			self.wrapper.addClass('movable');
			moveObj = self.container.makeMovable({handle : self.titler.parentNode.parentNode});
			if (!Browser.opera && !this.ie6) moveObj.addEvents({start : function(o){o.setStyle('opacity', .7);}, complete : function(o){o.setStyle('opacity',1);}.bind(self)});
		},
		ok : function(){
			var self = this,
                result = true;
			if(self.doValidate) result = self.doValidate(self);
			if(result && self.doOk && self.doOk(self)) self.close();
			return false;
		},
		cancel : function(){
			var self = this,
                result = true;
			if (self.doCancel) self.doCancel(self);
			self.close();
			return false;
		},
		show : function(pos){
            var self = this,
                ops = self.options;
			if (pos) self.container.setStyles(pos).show();
			else self.container.central().show();
			if(self.ie6) self.container.getFirst().setStyles({width : self.container.offsetWidth - 3, height : self.container.offsetHeight - 3});
            self.opacity.setStyle('height', self.container.offsetHeight + 10);
			self.showMask();
			clearTimeout(self.closeTimer);
			self.closeTimer = null;
			if(ops.closeDelay > 0) self.closeTimer = self._close.delay(ops.closeDelay, self);
			try{
				var btn = self.button;
				if(btn.ok.offsetWidth) btn.ok.focus();
				if(!btn.ok.offsetWidth && btn.cancel.offsetWidth) btn.cancel.focus();
			} catch(e){}
			return self;
		},
		getElements : function(path){
			return this.contenter.getElements(path);
		},
		getElement : function(path){
			return this.getElements(path)[0] || null;
		},
		id : function(id){
			return this.getElement('#' + id);
		},
		setWidth : function(width){
            var self = this;
			self.wrapper.setStyle('width', width);
			self.contenter.setStyle('width', width);
		},
		setHeight : function(height){
			this.contenter.setStyle('height', height);
		},
		setIndex : function(index){
            var self = this;
			self.container.setStyle('z-index', index + 1);
			if(self.masker) self.masker.setStyle('z-index', index);
			return self;
		},
		setTitle : function(html){
            var self = this;
			self.titler.set('html', html || '');
			return self;
		},
		setContent : function(html){
            var self = this;
			self.contenter.set('html', html || '');
			return self;
		},
		setButtons : function(ops){
			var self = this,
                cw = this.contenter.getStyle('width').toInt();
			if (ops.ok) {
				var ok = self.button.ok, ow = ok.getStyle('width').toInt();
				if (ops.ok.text) ok.getFirst().set('text', ops.ok.text);
				ok[ops.ok.show !== false ? 'show' : 'hide']();
				ok.setStyle('right', ops.ok.show !== false && ops.cancel.show == false ? (cw - ow)/ 2 : 125);
			}
			if (ops.cancel) {
				var cancel = self.button.cancel, aw = cancel.getStyle('width').toInt();
				if(ops.cancel.text) cancel.getFirst().set('text', ops.cancel.text);
				cancel[ops.cancel.show !== false ? 'show' : 'hide']();
				cancel.setStyle('right', ops.cancel.show !== false && ops.ok.show == false ? (cw - aw)/ 2 : 25);
			}
		},
		showMask : function(){
			var self = this,
                ops = this.options;
			if(!ops.mask) return;
			if(!self.masker){
				self.wrapper.addClass('modal');
				self.masker = new Element('div', {
					styles : { 'display' : 'none', position : 'absolute', width : '100%', left : 0, top : 0, 'z-index' : ops.index, background: '#999',opacity: .6 }
				}).inject(doc.body);
			}
			self.masker.setStyle('height', win.getScrollSize().y).show();
		},
		hideMask : function(){
            var masker = this.masker;
			masker && masker.hide();
		},
		update : function(ops){
            var self = this;
			if(ops){
				self.options.closeDelay = (typeof ops.closeDelay != undefined) ? parseInt(ops.closeDelay) : 0;
				self.options.mask = !!ops.mask;
				if(typeof ops.title != undefined) self.setTitle(ops.title);
				if(typeof ops.content != undefined) self.setContent(ops.content);
				if(ops.index) self.setIndex(ops.index);
				this.setWidth(ops.width || self.options.width);
				this.setHeight(ops.height || self.options.height);

				if(ops.desc){
					self.descHolder[ops.desc.show === true ? 'show' : 'hide']();
					if (ops.desc.icon) self.descTitler.setStyle('background-image', 'url(' + ops.desc.icon + ')');
					if (ops.desc.title) self.descTitler.set('html', ops.desc.title);
					if (ops.desc.content) self.descContenter.set('html', ops.desc.content);
				}
				
				if (ops.buttons) self.setButtons(ops.buttons);

				if (ops.doOk) self.doOk = ops.doOk;
				else delete self.doOk;
				if (ops.doCancel) self.doCancel = ops.doCancel;
				else delete self.doCancel;
				if (ops.doValidate) self.doValidate = ops.doValidate;
				else delete self.doValidate;
				if (ops.doClose) self.doClose = ops.doClose;
				else delete self.doClose;
			}
			return self;
		}
	});
	
	ns.ModelDialogManager = {
		getDialog : function(ops){
            var self = this;
			ops = ops || {};
			ops.index = 1000;
			if (!self.dialog) self.dialog = new ns.ModelDialog(ops);
			return self.dialog;
		},
		open : function(pos, ops){
			return this.show(pos, ops);
		},
		show : function(pos, ops){
            var self = this;
			self.getDialog(ops).show(pos);
			return self;
		},
		hide : function(){
			return this.close();
		},
		close : function(){
			var self = this;
            self.dialog && self.dialog.close();
			return self;
		},
		update : function(ops){
            var self = this;
			self.getDialog().update(ops);
			return self;
		}
	};

})(using('HB'), this, document);


//对话框
(function(ns){
	var Dialog = HB.ModelDialogManager;
	
	// 处理中
	ns.onProcess = function(options) {
		var op = Object.merge(
			{
			title : '处理中',
			mask : true,
			selectable : false,
			content : '<div class="process">正在处理，请稍候...</div>',
			buttons : { ok : { show : false }, cancel : { show : true, text : '关闭提示' } }
			},
			options
		), pos = op.position;
		delete op.position;
		
		return Dialog.update(op).show(pos);
	};
	// 完成
	ns.onComplete = function(options) {
		return Dialog.update(Object.merge({}, options)).close();
	}; 
	// 成功
	ns.onSuccess = function(options) {
		var op = Object.merge(
			{
			title : '完成',
			mask : true,
			selectable : false,
			content : '',
			buttons : { ok : { show : false }, cancel : { show : true, text : '关闭' } }
			},
			options
		), pos = op.position;
		delete op.position;
		
		return Dialog.update(op).show(pos);
	};
	// 错误
	ns.onError = function(options) {
		var op = Object.merge(
			{
			title : '错误',
			content : '服务器忙,是否重试?',
			mask : true,
			selectable : false,
			buttons : { ok : { show : true, text : '重试' }, cancel : { show : true, text : '取消' } }
			},
			options
		), pos = op.position;
		delete op.position;
		
		return Dialog.update(op).show(pos);
	};
	// 确认
	ns.Confirm = function(options) {
		var op = Object.merge(
			{
			title : '消息确认',
			content : '',
			mask : true,
			selectable : false,
			buttons : { ok : { show : true, text : '确定' }, cancel : { show : true, text : '取消' } }
			},
			options
		), pos = op.position;
		delete op.position;
		op.content = '<table cellspacing="5" cellpadding="10" class="confirm" align="center"><tr><td class="text">' + op.content + '</td></tr></table>';
		if(op.doCancel && !op.doClose) op.doClose = op.doCancel;
		if(!op.doCancel && op.doClose) op.doCancel = op.doClose;
		
		return Dialog.update(op).show(pos);
	};
	ns.Alert = function(options){
        if (typeOf(options) == 'string') {
            options = {content: options};
        }
		var op = Object.merge({
			title : '信息提示',
			mask : true,
			selectable : false,
			buttons : { ok : { show : false }, cancel : { show : true, text : '确定' } }
			},
			options
		), pos = op.position;
		delete op.position;
		op.content = '<table cellspacing="5" cellpadding="10" class="alert" align="center"><tr><td class="text">' + op.content + '</td></tr></table>';
		if(op.doCancel && !op.doClose) op.doClose = op.doCancel;
		if(!op.doCancel && op.doClose) op.doCancel = op.doClose;
		if(op.doOk && !op.doCancel) op.doCancel = op.doOk;
		
		return Dialog.update(op).show(pos);
	};
})(using('App'));